package com.crane.oss.school.service.impl;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

import javax.annotation.Resource;

import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.ObjectUtils;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.crane.common.core.exception.AppException;
import com.crane.common.core.exception.BasicErrorCode;
import com.crane.common.core.exception.SysException;
import com.crane.common.framework.utils.BeanUtil;
import com.crane.common.framework.utils.DateUtil;
import com.crane.oss.enums.TaskSubTypeEnum;
import com.crane.oss.school.bean.request.QueryStudentSkipropeReq;
import com.crane.oss.school.bean.request.studentskiprope.AddStudentSkipropeReq;
import com.crane.oss.school.bean.request.studentskiprope.QueryStudentTodaySkipRopeReq;
import com.crane.oss.school.bean.request.studentskiprope.UpdateStudentSkipropeReq;
import com.crane.oss.school.bean.request.task.QueryHistoryDataReq;
import com.crane.oss.school.bean.request.task.QueryRankReq;
import com.crane.oss.school.bean.resp.HistoryFlagResp;
import com.crane.oss.school.bean.resp.HistorySkipRopeResp;
import com.crane.oss.school.bean.resp.HistoryTimeSkipRopeResp;
import com.crane.oss.school.bean.resp.RankSkipRope;
import com.crane.oss.school.bean.resp.RankSkipRopeResp;
import com.crane.oss.school.bean.resp.SkipRopeModelResp;
import com.crane.oss.school.bean.resp.TaskStudentSkipRopeResp;
import com.crane.oss.school.bean.resp.TodaySkipRopeResp;
import com.crane.oss.school.bean.resp.TopSkipRopeResp;
import com.crane.oss.school.dao.StudentSkipropeDao;
import com.crane.oss.school.model.StudentSkiprope;
import com.crane.oss.school.service.StudentSkipropeService;

import lombok.extern.slf4j.Slf4j;

/**
 *
 * @author zhenxing.pi
 * @email ccsu123456@qq.com
 * @date 2023年01月17日 23时03分27秒
 */
@Service
@Slf4j
public class StudentSkipropeServiceImpl implements StudentSkipropeService {

	@Resource
	protected StudentSkipropeDao studentSkipropeDao;

	@Override
	public TaskStudentSkipRopeResp queryStudentSkiprope(Long id) {
		log.info("StudentSkipropeBOImpl queryStudentSkiprope id={}", id);
		StudentSkiprope studentSkiprope = studentSkipropeDao.selectById(id);
		if (null == studentSkiprope) {
			throw new AppException(BasicErrorCode.ENTITY_NOT_EXISTS, "studentSkiprope");
		}
		TaskStudentSkipRopeResp studentSkipropeResp = new TaskStudentSkipRopeResp();
		BeanUtil.copyProperties(studentSkiprope, studentSkipropeResp);
		return studentSkipropeResp;
	}

	@Override
	public IPage<TaskStudentSkipRopeResp> queryList(QueryStudentSkipropeReq queryRequest) {
		log.info("StudentSkipropeBOImpl queryList queryRequest={}", queryRequest);
		IPage<TaskStudentSkipRopeResp> result = new Page<>();
		result.setCurrent(queryRequest.getPageNo());
		result.setPages(queryRequest.getPageSize());

		LambdaQueryWrapper<StudentSkiprope> queryStudentSkipropeWrapper = new LambdaQueryWrapper<>();
		IPage<StudentSkiprope> page = studentSkipropeDao.selectPage(
				new Page<>(queryRequest.getPageNo(), queryRequest.getPageSize()), queryStudentSkipropeWrapper);
		return page.convert(u -> {
			TaskStudentSkipRopeResp v = new TaskStudentSkipRopeResp();
			BeanUtils.copyProperties(u, v);
			return v;
		});
	}

	@Override
	@Transactional(rollbackFor = Exception.class)
	public int save(AddStudentSkipropeReq addRequest) {
		log.info("StudentSkipropeBOImpl save request={}", addRequest);
		StudentSkiprope studentSkiprope = new StudentSkiprope();
		BeanUtil.copyProperties(addRequest, studentSkiprope);
		int i = 0;
		try {
			i = studentSkipropeDao.insert(studentSkiprope);
		} catch (Exception e) {
			log.info("StudentSkipropeBOImpl add e={}", e);
			throw new SysException();
		}
		return i;
	}

	@Override
	@Transactional(rollbackFor = Exception.class)
	public int update(UpdateStudentSkipropeReq updateRequest) {
		log.info("StudentSkipropeServiceImpl update request={}", updateRequest);
		StudentSkiprope studentSkiprope = new StudentSkiprope();
		BeanUtil.copyProperties(updateRequest, studentSkiprope);
		int i = 0;
		try {
			i = studentSkipropeDao.updateById(studentSkiprope);
		} catch (Exception e) {
			log.info("StudentSkipropeServiceImpl add e={}", e);
			throw new SysException();
		}
		return i;
	}

	@Override
	@Transactional(rollbackFor = Exception.class)
	public int delete(Long id) {
		log.info("StudentSkipropeServiceImpl delete id={}", id);
		return studentSkipropeDao.deleteById(id);
	}

	@Override
	public RankSkipRopeResp queryRank(QueryRankReq request) {
		log.info("StudentSkipropeServiceImpl queryHistoryData request={}", request);
		RankSkipRopeResp returnResp = new RankSkipRopeResp();
		request.setUpperLimit(500);

		if (request.getType() == 2) {
			request.setType(null);
			request.setUpperLimit(1000);
		}

		Date date = new Date();
		request.setStartTime(DateUtil.getStartDate(date));
		request.setEndTime(date);

		if (request.getTime() == 2) {
			request.setStartTime(DateUtil.parseFullDateTime(DateUtil.weekStart(date)));
			request.setEndTime(date);
		}

		if (request.getTime() == 3) {
			request.setStartTime(DateUtil.parseFullDateTime(DateUtil.monthStart(date)));
			request.setEndTime(date);
		}

		if (request.getTime() == 4) {
			request.setStartTime(DateUtil.parseFullDateTime(DateUtil.yearStart(date)));
			request.setEndTime(date);
		}

		returnResp.setRankList(this.queryRankListForPage(request));

		List<RankSkipRope> queryRankList =  studentSkipropeDao.queryRankList( request);

		int myRank = 0;
		int myQuantity = 0;
		for (RankSkipRope rank : queryRankList) {
			myRank = myRank+1;
			if (rank.getStudentId() == request.getStudentId()) {
				myQuantity = rank.getQuantity();
				break;
			}
		}
		returnResp.setMyRank(myRank);
		returnResp.setMyQuantity(myQuantity);
		if (myQuantity == 0) {
			RankSkipRope queryRank = studentSkipropeDao.queryRankForStudentId(request);
			if (null != queryRank) returnResp.setMyQuantity(queryRank.getQuantity());
		}

		return returnResp;
	}

	@Override
	public HistorySkipRopeResp queryHistoryData(QueryHistoryDataReq request) {
		log.info("StudentSkipropeServiceImpl queryHistoryData request={}", request);
		HistorySkipRopeResp returnResp = new HistorySkipRopeResp();

		Date startTime = DateUtil.parseFullDateTime(request.getStartTime());

		QueryStudentTodaySkipRopeReq monthRequest = new QueryStudentTodaySkipRopeReq();
		monthRequest.setStudentId(request.getStudentId());
		monthRequest.setStartTime(DateUtil.parseFullDateTime(DateUtil.monthStart(startTime)));
		monthRequest.setEndTime(DateUtil.parseFullDateTime(DateUtil.monthEnd(startTime)));
		TodaySkipRopeResp queryMonthResp = studentSkipropeDao.queryTodaySkipRope(monthRequest);
		HistoryTimeSkipRopeResp monthSkipRope = new HistoryTimeSkipRopeResp();
		if(null != queryMonthResp.getSkipPopeCount()){
			queryMonthResp.setAvgFrequency(new BigDecimal(queryMonthResp.getSkipPopeCount()).multiply(new BigDecimal(60)).divide(new BigDecimal(queryMonthResp.getTimes()),2, RoundingMode.HALF_UP).doubleValue());
			BeanUtil.copyProperties(queryMonthResp, monthSkipRope);
		}
		returnResp.setMonthSkipRope(monthSkipRope);
		QueryStudentTodaySkipRopeReq dayRequest = new QueryStudentTodaySkipRopeReq();
		dayRequest.setStudentId(request.getStudentId());
		dayRequest.setStartTime(DateUtil.getStartDate(startTime));
		dayRequest.setEndTime(DateUtil.getEndDate(startTime));
		TodaySkipRopeResp queryDayResp = studentSkipropeDao.queryTodaySkipRope(dayRequest);
		HistoryTimeSkipRopeResp daySkipRope = new HistoryTimeSkipRopeResp();
		if(null != queryDayResp.getSkipPopeCount()){
			queryDayResp.setAvgFrequency(new BigDecimal(queryDayResp.getSkipPopeCount()).multiply(new BigDecimal(60)).divide(new BigDecimal(queryDayResp.getTimes()),2, RoundingMode.HALF_UP).doubleValue());
			BeanUtil.copyProperties(queryDayResp, daySkipRope);
		}
		returnResp.setDaySkipRope(daySkipRope);
		returnResp.setDaySkipRopeList(this.queryHistoryList(request));

		List<HistoryFlagResp> flagList = new ArrayList<HistoryFlagResp>();
		Date flagStartDate =  DateUtil.parseFullDateTime(DateUtil.monthStart(startTime));
		Date flagEndDay = DateUtil.parseFullDateTime(DateUtil.monthEnd(startTime));
		int daysBetween = DateUtil.daysBetween(flagEndDay, flagStartDate);
		for (int i=0;i<=daysBetween;i++) {
			Date forFirstDate = DateUtil.stipulateDateAddDay(flagStartDate,i);
			Date forEndDate = DateUtil.getEndDate(forFirstDate);

			QueryStudentTodaySkipRopeReq flagDayRequest = new QueryStudentTodaySkipRopeReq();
			flagDayRequest.setStudentId(request.getStudentId());
			flagDayRequest.setStartTime(forFirstDate);
			flagDayRequest.setEndTime(forEndDate);
			TodaySkipRopeResp flagQueryDayResp = studentSkipropeDao.queryTodaySkipRope(flagDayRequest);

			HistoryFlagResp flagResp = new HistoryFlagResp();
			flagResp.setFirstDate(forFirstDate);
			flagResp.setEndDate(forEndDate);
			flagResp.setFlag(true);

			if (flagQueryDayResp.getDurationCount() == 0) {
				flagResp.setFlag(false);
			}
			flagList.add(flagResp);
		}
		returnResp.setFlagList(flagList);

		return returnResp;
	}

	private IPage<RankSkipRope> queryRankListForPage(QueryRankReq request) {
        IPage<RankSkipRope> result = new Page<>();
        result.setCurrent(request.getPageNo());
        result.setPages(request.getPageSize());

        IPage<RankSkipRope> page =  studentSkipropeDao.queryRankListForPage(new Page<>(request.getPageNo(), request.getPageSize()), request);
        return page.convert(u -> {
			if (u.getStudentName().length() == 2) {
				String temp = u.getStudentName().replaceFirst(u.getStudentName().substring(1), "*");
				u.setStudentName(temp);
			}
			if (u.getStudentName().length() > 2) {
				String temp = u.getStudentName().replaceFirst(u.getStudentName().substring(1,u.getStudentName().length()-1), "*");
				u.setStudentName(temp);
			}
            return u;
        });
	}

    private IPage<SkipRopeModelResp> queryHistoryList(QueryHistoryDataReq request) {
        log.info("StudentSkipropeServiceImpl queryHistoryList queryRequest={}", request);
        IPage<SkipRopeModelResp> result = new Page<>();
        result.setCurrent(request.getPageNo());
        result.setPages(request.getPageSize());

        Date startTime = DateUtil.parseFullDateTime(request.getStartTime());

        LambdaQueryWrapper<StudentSkiprope> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(ObjectUtils.isNotNull(request.getStudentId()), StudentSkiprope::getStudentId, request.getStudentId());
        queryWrapper.ge(StudentSkiprope::getBeginTime, DateUtil.getStartDate(startTime));
        queryWrapper.le(StudentSkiprope::getEndTime, DateUtil.getEndDate(startTime));
        queryWrapper.orderByDesc(StudentSkiprope ::getBeginTime);

        IPage<StudentSkiprope> page = studentSkipropeDao.selectPage(new Page<>(request.getPageNo(), request.getPageSize()), queryWrapper);
        return page.convert(u -> {
        	SkipRopeModelResp v = new SkipRopeModelResp();
            BeanUtils.copyProperties(u, v);
            v.setModelName(TaskSubTypeEnum.getTaskSubTypeName(u.getModel()));
            return v;
        });
    }

	@Override
	public TodaySkipRopeResp queryTodaySkipRope(Long studentId) {
		log.info("StudentSkipropeServiceImpl queryTodaySkipRope studentId={}", studentId);
		QueryStudentTodaySkipRopeReq req = new QueryStudentTodaySkipRopeReq();
		req.setStartTime(DateUtil.getStartDate(new Date()));
		req.setEndTime(DateUtil.getEndDate(new Date()));
		req.setStudentId(studentId);
		TodaySkipRopeResp resp = studentSkipropeDao.queryTodaySkipRope(req);
		if(null != resp.getSkipPopeCount()){
			resp.setAvgFrequency(new BigDecimal(resp.getSkipPopeCount()).multiply(new BigDecimal(60)).divide(new BigDecimal(resp.getTimes()),2, RoundingMode.HALF_UP).doubleValue());
		}
		resp.setTopList(this.queryTopSkipRope(studentId));
		return resp;
	}

	@Override
	public List<TopSkipRopeResp> queryTopSkipRope(Long studentId) {
		log.info("StudentSkipropeServiceImpl queryTopSkipRope studentId={}",studentId);
		List<Integer> subTypeList = new ArrayList<>();
		for (TaskSubTypeEnum subTypeEnum : TaskSubTypeEnum.values()) {
			subTypeList.add(subTypeEnum.getType());
		}

		List<TopSkipRopeResp> respList = new ArrayList<>();
		for (Integer subType : subTypeList) {
			TopSkipRopeResp resp = studentSkipropeDao.queryTopSkipRope(Long.valueOf(subType), studentId);
			respList.add(resp);
		}
		return respList;
	}

}
